﻿using System;
using System.IO;
using System.Linq;
using System.Web;
using Web.Pages;    

namespace Web.Helpers
{
    public class FileHelper
    {
        public static string GetServerFilename(string filename)
        {
            return HttpContext.Current.Server.MapPath(filename);
        }
        public static string GetServerRoot()
        {
            /*
                Server.MapPath(".")     => D:\WebApps\shop\products ( Server.MapPath(null) and Server.MapPath("") has the same effect )
                Server.MapPath("..")    => D:\WebApps\shop
                Server.MapPath("~")     => D:\WebApps\shop
                Server.MapPath("/")     => C:\Inetpub\wwwroot
                Server.MapPath("/shop") => D:\WebApps\shop
            */
            return HttpContext.Current.Request.PhysicalApplicationPath; //HttpContext.Current.Server.MapPath("~");
        }
        public static string GetSafeFilename(string filePath, string filename)
        {
            filename            = RemoveIllegalCharsFromFilename(filename);
            var root            = GetServerRoot();
            var fileNameOnly    = Path.GetFileNameWithoutExtension(filename);
            var extension       = Path.GetExtension(filename);
            //var path            = Path.GetDirectoryName(fullFileName);
            //filename            = filePath + '/' + filename;
            var count = 1;
            
            var fullFileName = root + filePath + '/' + filename;
            while ( File.Exists(fullFileName) )
            {
                var tempFileName = string.Format( "{0} ({1}){2}", fileNameOnly, count++, extension );
                fullFileName = root  + filePath + '/' + tempFileName;
            }

            return fullFileName;
        }
        public static string RemoveIllegalCharsFromFilename(string fileName)
        {
            return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty));
        }
        //public static string SaveFile(Stream stream, string path, string filename)
        //{
        //    var root = GetServerRoot();
        //    filename = root + path + filename;

        //    var fileStream = File.Create(filename, (int)stream.Length);

        //    // Initialize the bytes array with the stream length and then fill it with data
        //    var bytesInStream = new byte[stream.Length];
        //    stream.Position = 0;
        //    stream.Read(bytesInStream, 0, bytesInStream.Length);    
        //    // Use write method to write to the file specified above
        //    fileStream.Write(bytesInStream, 0, bytesInStream.Length);
        //    fileStream.Close();
        //    stream.Close();
        //    fileStream.SafeDispose();
        //    stream.SafeDispose();

        //    return filename;
        //}
        public static string SaveFile(Stream stream, string path, string filename)
        {
            // Initialize the bytes array with the stream length and then fill it with data
            var bytesInStream = new byte[stream.Length];
            stream.Position = 0;
            stream.Read(bytesInStream, 0, bytesInStream.Length);

            filename = SaveFile(bytesInStream, path, filename);

            stream.SafeClose();
            stream.SafeDispose();

            return filename;
        }
        public static string SaveFile(byte[] content, string path, string filename)
        {
            var root = GetServerRoot();
            filename = root + path + filename;

            var fileStream = File.Create(filename, content.Length);
            fileStream.Write(content, 0, content.Length);

            fileStream.SafeClose();
            fileStream.SafeDispose();

            return filename;
        }
        public static DirectoryInfo CreateDirectory(string path)
        {
            var root = GetServerRoot();
            return Directory.CreateDirectory(root + path);
        }
        public static void DeleteDirectory(string path)
        {
            var root = GetServerRoot();
            try
            {
                Directory.Delete(root + path, true);
            }
            catch (Exception)
            {
                // throw;
            }
        }
        public static Stream ReadFileInfoStream(string filePath)
        {
            var memStream = new MemoryStream();
            using (var fileStream = File.OpenRead(filePath))
            {
                memStream.SetLength(fileStream.Length);
                fileStream.Read(memStream.GetBuffer(), 0, (int) fileStream.Length);
            }
            return memStream;
        }
        public static byte[] ReadBytesFromStream(Stream stream)
        {
            var fileContent = new byte[stream.Length];
            stream.Read(fileContent, 0, fileContent.Length);
            stream.SafeClose();
            stream.SafeDispose();
            return fileContent;
        }
        public static void CopyFiles(string sourcePath, string targetPath, string[] files = null)
        {
            var root = GetServerRoot();
            sourcePath = root + sourcePath;
            targetPath = root + targetPath;
            if (Directory.Exists(sourcePath))
            {
                if (!Directory.Exists(targetPath) )
                    Directory.CreateDirectory(targetPath);

                var allFiles = Directory.GetFiles(sourcePath);
                //Copy the files and overwrite destination files if they already exist.
                foreach (var file in allFiles)
                {
                    //Use static Path methods to extract only the file name from the path.
                    var fileName = Path.GetFileName(file);
                    var targetFilename = Path.Combine(targetPath, fileName);
                    if (files != null && files.Length > 0)
                    {
                        if (files.Contains(fileName))
                            File.Copy(file, targetFilename, true);
                    }
                    else
                    {
                        File.Copy(file, targetFilename, true);
                    }
                }
            }
        }

        public static void RunExecutable(string fileName, string[] parameters = null)
        {
            AppDomain appDomain = null;

            var domainName = String.Empty;

            try
            {
                var appDomainsetup = new AppDomainSetup
                {
                    CachePath = AppDomain.CurrentDomain.SetupInformation.CachePath, // this prevents "random" FileLoadException issue!
                    ApplicationBase = Environment.CurrentDirectory
                };
                appDomainsetup.SetCompatibilitySwitches(new[] {"NetFx40_LegacySecurityPolicy"});
                domainName = DateTime.Now.ToString("yyyyMMddHHmmss f ff fff ffff").Replace(" ", String.Empty);
                appDomain = AppDomain.CreateDomain(domainName, null, appDomainsetup);
                if (parameters == null)
                    appDomain.ExecuteAssembly(fileName);
                else
                    appDomain.ExecuteAssembly(fileName, parameters);
            }
            //catch (ArgumentNullException ex)
            //{
            //    BasePage.LogError(ex);
            //    throw;
            //}
            //catch (FileNotFoundException ex)
            //{
            //    BasePage.LogError(ex);
            //    throw;
            //}
            //catch (BadImageFormatException ex)
            //{
            //    BasePage.LogError(ex);
            //    throw;
            //}
            //catch (AppDomainUnloadedException ex)
            //{
            //    BasePage.LogError(ex);
            //    throw;
            //}
            //catch (FileLoadException ex)
            //{
            //    var message = "FileLoadException debugging info";
            //    var allParameters = String.Empty;
            //    if ( parameters != null )
            //        allParameters = String.Join(",", parameters);
            //    var details = String.Format("domainName: [{0}], parameters: [{1}]", domainName, allParameters);
            //    BasePage.LogMessage( message, details );

            //    BasePage.LogError(ex);
            //    throw;
            //}
            //catch (MissingMethodException ex)
            //{
            //    BasePage.LogError(ex);
            //    throw;
            //}
            catch (Exception)
            {
                //BasePage.LogError(ex);
                //throw;
            }
            finally
            {
                try
                {
                    if (appDomain != null)
                        AppDomain.Unload(appDomain);
                }
                //catch (ArgumentNullException ex)
                //{
                //    BasePage.LogError(ex);
                //    throw;
                //}
                //catch (CannotUnloadAppDomainException ex)
                //{
                //    BasePage.LogError(ex);
                //    throw;
                //}
                catch (Exception)
                {
                    //BasePage.LogError(ex);
                    //throw;
                }
            }           
        }
    }
}